El principal objetivo del taller es familiarizarse con el sistema de control de versiones automatizado Git y el repositorio remoto GitHub. Ambas herramientas están ganando cada vez más importancia en ecología a medida que el volumen de datos aumenta y los análisis de hacen más complejos. En el taller aprenderemos cómo Git puede usarse para controlar la trazabilidad de los cambios realizados en proyectos o archivos y veremos cómo este control de versiones es especialmente útil en proyectos colaborativos mediante el uso de repositorios remotos como GitHub.
Por ejemplo, Git y GitHub nos pueden ayudar a solucionar algunos problemas comunes derivados de la creación de diferentes versiones que pueden ser un poco molestos:
- Sobreescritura de un archivo
- Versiones finales infinitas
- Trabajo por error en una versión que no era la final
- Creación de copias “en conflicto” cuando dos personas trabajan a la vez
- Ediciones sin control de cambios
| Bloques | Tiempo estimado |
|---|---|
| Introducción | 20 min |
| Instalación | 20 min |
| Repositorios y proyectos | 10 min |
| Flujo de trabajo en Git y GitHub | 50 min (30 min explicación y ejemplo + 20 min ejercicios) |
| Descanso | 20 min |
| La he liado ¿cómo deshago los cambios? | 30 min (15 + 15) |
| ¿Cómo se puede trabajar paralelamente? | 40 min (20 + 20) |
| Descanso | 10 min |
| Otros comandos útiles | 10 min |
| Otras utilidades de Github | 10 min |
| 30 min |
Y vosotros ¿quiénes sois?
https://www.menti.com/8fnfxiwrk7
Git es un sistema avanzado de control de versiones, similar al “control de cambios” de Microsoft Word. Git permite “rastrear” el progreso de un proyecto a lo largo del tiempo. Puedes volver atrás y ver los cambios que se hicieron, ya que Git hace “capturas” del proyecto a medida que evoluciona y los cambios se van guardando. Permite al resto de participantes del proyecto mantenerse al día con las actualizaciones y desandar los pasos que se han dado si es necesario. Además, Git facilita el trabajo en paralelo de varios participantes. En otros sistemas de control de versiones hay un servidor central. Cualquier cambio hecho por un usuario se sincroniza con este servidor y de ahí con el resto de usuarios. Si dos personas están trabajando a la vez y guardan, se crean conflictos (p. ej. en Dropbox). En cambio Git es un control de versiones distribuído que permite a todos los usuarios trabajar en el proyecto paralelamente e ir haciendo “capturas” del trabajo de cada uno, facilitando así la sincronización de los cambios.
GitHub es una plataforma online para albergar proyectos basados en Git que permite la colaboración de diferentes usuarios (similar a Google Drive o Microsoft Teams). GitHub permite que otros usuarios vean y utilicen tus proyectos e incluso que te propongan cambios. GitHub es útil para trabajar en remoto y poder acceder a tus proyectos desde cualquier ordenador además de proporcionar la seguridad de la nube.
En este punto es necesario que tengas instalada la versión más reciente de R, RStudio, Git y una cuenta en GitHub creada. A continuación tienes que seguir los siguientes pasos:
Presentarte a Git (Chapter 7: Git-Intro)
Conectar tu ordenador de trabajo a GitHub (Chapter 9: Connect to GitHub)
Conectar RStudio a Git y GitHub (Chapter 12: Connect RStudio to Git and GitHub)
En la terminal, compueba que has instalado Git correctamente:
Tools -> Shell
git --version
Para ver el usuario utilizado para configurar Git:
git config user.name
Para ver a qué cuenta de correo está asociado Git:
git config user.email
⚡ ¿Qué es el la terminal? La terminal (o shell) es un programa en tu ordenador cuyo trabajo es ejecutar otros programas. En este workshop aprenderemos a trabajar principalmente con el shell aunque también veremos cómo hacerlo a través de un cliente (RStudio).
Un repositorio es como un “contenedor” donde desarrollar un proyecto.
Para crear un repositorio en GitHub damos a “+ New repository”. Aquí se indica el nombre, una pequeña descripción, y si quieres que sea público o privado. Se recomienda iniciar el repositorio con un archivo “README” (Initialize this repository with a README) para recoger cualquier información esencial para el uso del repositorio (estructura, descripción más detallada del contenido, etc.).
En R, creamos un nuevo proyecto y lo conectamos al repositorio: File -> New project -> Version control -> Git -> copiar el URL del repositorio que hemos creado de GitHub (está en la página principal de nuestro repositorio, en “clone or download”). Seleccionamos el directorio donde queremos guardar el proyecto y pulsamos en “Create project”.
Si vamos al directorio seleccionado, encontraremos la carpeta conectada a Git y GitHub que hemos creado en nuestro ordenador. Podemos copiar aquí todos los archivos que nos interesan para el proyecto (datos, imágenes, etc).
Trabajamos en equipos de 2-3 personas.
Un integrante del equipo crea un repositorio en GitHub y lo conecta a un nuevo proyecto de RStudio
Crea un nuevo script de R en el directorio de trabajo.
En RStudio ve a la pestaña Git (donde está el environment) para ver todos los documentos que hemos añadido en el repositorio local
Hay cuatro “zonas” de trabajo:
Directorio de trabajo (working directory): es donde estás trabajando. Este árbol se sincroniza con los archivos locales de tu PC.
Área de preparación (staging area): es la zona intermedia entre el directorio de trabajo y el repositorio local. Registra los cambios que se especifican en el directorio. También se denomina Index.
Repositorio local (local repository): es donde se almacenan todos los cambios en tu PC. También se llama HEAD.
Repositorio remoto (remote repository): es donde se almacenan todos los cambios en la nube.
Al principio todos los cambios realizados están en amarillo porque Git no sabe que hacer con ellos. Estamos en el directorio de trabajo y puede que no nos interese guardar todos los cambios para el futuro.
Para añadir un cambio del directorio de trabajo al área de preparación hay que utilizar git add. Indica a Git que quieres incluir las actualizaciones de algún archivo en el próximo commit. Sin embargo, git add no afecta realmente al repositorio local de forma significativa. Los cambios no se guardan hasta que se ejecuta el git commit.
git add <file>: registra todos los cambios en el archivo llamado file para el siguiente commit.Para ver el estado del directorio de trabajo y del área de preparación se utiliza git status. Permite ver qué cambios han sido añadidos al área de preparación (staged), cuáles no, y qué archivos no están siendo rastreados por Git.
Para registrar los cambios que nos interesen hay que utilizar git commit. Al hacer un commit haremos una captura del estado del proyecto (snapshot). Junto con el commit añadiremos un mensaje que es recomendable poner una pequeña explicación de que has cambiado y por qué (p. ej. decimocuarta revisión del capítulo 3 de la tesis con cambios de director1). Cada git commit tiene un SHA (Secure Hash Algorithm) que es algo así 1d21fc3c33cddc4aeb7823400b9c7c6bc2802be1. Parece difícil de entender, pero no te preocupes, sólo tienes que recordar los seis primeros dígitos 1d21fc 🤯 (es broma). Con el SHA puedes ver los cambios que se hicieron en ese commit. Si algo sucede, esa parte se guarda para que puedas volver allí fácilmente.
git commit -m "mensaje corto y descriptivo"Por último, con git push subiremos los cambios que hemos hecho a GitHub (repositorio remoto) y quedarán visibles para nuestros colaboradores. Basicamente, git commit registra los cambios en el repositorio local y git push actualiza el repositorio remoto con los cambios y archivos asociados.
git add + git commit + git push).Cuando retomamos un proyecto (tras horas o días), con git pull se descargan todas las actualizaciones que haya en GitHub (nuestras o de nuestros colaboradores), que se fusionarán (merge) con el último commit.
Para dar acceso de edición a tus colaboradores, en la página principal de nuestro proyecto en GitHub entramos en “Settings -> Manage Access -> Invite a collaborator”. Los colaboradores crean un nuevo proyecto de control de versiones clonando el repositorio remoto (por ejemplo esto se puede hacer copiando el https del proyecto).
Cuando hago un cambio que no quiero ¿cómo lo puedo resolver? Hay múltiples opciones pero aquí detallamos tres: restore, reset y revert. Restore se usa cuando no has llegado a hacer un commit con los cambios que quieres añadir y reset/revert cuando si has hecho un commit con los cambios.
git restore: deshace un git add y/o los cambios del directorio de trabajo.
git restore <file>: descarta los cambios en un archivo al estado del último commit. ⚡ Esta opción es peligrosa ya que borra los cambios no commitidos de tu directorio de trabajo.
git restore --staged <file>: eliminará el archivo del área de preparación pero mantiene los cambios.
git reset: deshace un git commit y/o un git add y/o los cambios del directorio de trabajo.
git reset --mixed HEAD~1: deshace el add y el commit pero no los cambios realizados en el directorio de trabajo. Es equivalente a git reset (es decir, la opción por defecto). El HEAD~1 significa el commit anterior al head. Puedes ir un commit hacia atrás, dos, etc. También se puede utilizar el SHA en lugar del HEAD~X para ir a un commit específico.
git reset --hard HEAD~1: deshace el add, el commit y todos los cambios realizados en el directorio de trabajo. ☠️ Esta es la opción más PELIGROSA. Ten en cuenta que borra los cambios no commitidos de tu directorio de trabajo y apunta tu rama al commit especificado. Recomendamos ejecutar primero git status y ver si hay cambios no commitidos. Si los hay y no estás seguro de si los quieres conservar, guárdalos con git stash (más adelante explicaremos su utilidad).
git reset --soft HEAD~1: deshace el último commit pero no los add y los cambios realizados en el directorio de trabajo.
git revert HEAD~1: es la opción segura de git reset para deshacer un commit ya que no resetea un proyecto a su estado anterior eliminando todos los commits posteriores (es decir, no elimina el historial de commits). Recomendamos usar git reset en ramas que no hayan sido compartidas todavía (es decir, que no hayan sido commitidas a un repositorio remoto que otros estén usando). Resetear es cambiar el historial sin dejar rastro. Esto es siempre una mala práctica y puede causar problemas. Si queremos deshacer los cambios en las ramas que se comparten con otros, recomendamos utilizar el comando git revert. Con git revert quedará constancia de que se ha deshecho un cambio.git reset --soft HEAD~1git reset --mixed HEAD~1git reset --hard HEAD~1 💀¿Qúe comando habéis utilizado para ver las diferencias entre los distintos tipos de git reset?
Podemos crear una “rama” paralela al proyecto si deseamos seguir una línea independiente de trabajo, bien por ser diferente de la principal (p. ej., probar un nuevo análisis que piensas que puede sustituir al que ya se ha hecho) o bien para desarrollar específicamente una parte (p. ej., voy a trabajar sólo en la escritura de los métodos de un artículo). Las ramas permiten trabajar en el proyecto sin interferir con lo que puedan estar haciendo tus compañeros.
En el mundo Git, una rama es básicamente un puntero a un commit específico SHA (es un commit al que le damos un nombre). La rama “main” es la rama por defecto cuando creamos un repositorio. Las demás ramas se crean con git checkout.
git checkout -b <branchname>: crea una nueva rama y te cambia a ella.
git checkout main: para volver a la rama principal.
Cuando el trabajo desarrollado en una rama se da por finalizado y se quiere unir a la rama principal (“main”) hay que hacer la union utilizando el comando git merge.
git checkout <rama principal>: posiciono el puntero de Git en el último commit de la rama principal a la que quiero unir la otra rama.
git merge <rama a unir>: fusiona los cambios hechos en las dos ramas.
Esto se puede hacer en el terminal como acabamos de ver pero también se puede hacer fácilmente con el boton “pull request” en la página del proyecto en GitHub.
Git puede encontrar conflictos al fusionar ramas y tendrás que arreglarlos manualmente. Esto ocurrirá si en las dos ramas se ha cambiado el mismo trozo de un archivo. Git te mostrará dónde están los conflictos así (imaginemos que estamos uniendo la rama analisis al main):
\<\<\<\<\<\<código del main=======código de la rama analisis\>\>\>\>\>\>.
Para solucionarlo simplemente escoje los cambios de la rama principal o de la rama analisis según corresponda. Una vez solucionados te dejará completar el merge (es decir, un nuevo commit que contendrá las ramas fusionadas).
git diff: muestra los cambios no añadidos con git add
git log: muestra el historial de los commit
git add .: registra todos los cambios a la vez
git rm --cached filename: elimina un archivo del Index (dejaría de estar en el área en preparación). Muy útil si has commitido un archivo de 10GB 😉
git branch -d <branchname>: elimina la rama llamada branchname de tu pc
git push origin --delete <branchname>: elimina la rama remota llamada branchname (por ejemplo, desde GitHub). Ten en cuenta que la rama local y la remota no tienen nada que ver entre sí, por lo que deben eliminarse por separado
git branch -a: muestra todas las ramas locales y remotas. También te indica en qué rama te encuentras
git stash: cuando no quieres hacer un commit del trabajo a medio hacer pero quieres volver a este punto más tarde
git stash list: ver los stash que has guardado
git stash apply: recupera cualquier stash que has guardado en la stash list
git commit --amend -m "message": cambiar el mensaje del último commit.
git checkout HEAD~X: para inspeccionar una versión antigua del proyecto. Recomendamos crear una rama primero si se quiere añadir commits a partir de este punto temporal.
Al crear un repositorio se recomienda crear un archivo “.gitignore”. Este archivo contendrá los nombres o extensiones de los archivos del proyecto que por defecto no queremos compartir aunque estén en el repositorio local. P. ej., el archivo “.Rhistory” que RStudio crea por defecto. Es una buena práctica ignorar archivos muy pesados (p. ej., una base de datos resultado de correr un script) para no subirlos y descargarlos continuacmente de GitHub. Para añadir archivos al gitignore se puede utilizar el botón derecho del ratón sobre el archivo en la pestaña Git de RStudio.
En la página principal de tu proyecto en GitHub encontrarás herramientas útiles para colaborar.
“Issues”: permite incluir tareas para acordarte de lo que tienes que hacer o asignar tareas a los miembros del proyecto (escribiendo “@” antes del nombre del colaborador). Cuando completas una tarea, puedes conectar el issue con el commit correspondiente si en el mensaje del commit añades git commit -m "Close #XX" (p. ej., “Close #1” para cerrar el “issue” número 1).
“Fork”: GitHub contiene multitud de proyectos públicos que todos los usuarios pueden clonar y desarrollar independientemente. Al hacer una clonación, se crea una ramificación o copia del proyecto (“fork”) que pasa a formar parte de tu cuenta de usuario en GitHub. En caso de que desees unir los cambios realizados al proyecto original, deberás solicitarlo (=“pull request”). El dueño del proyecto decide si acepta o no los cambios que propones.
Session Info
Sys.time()
[1] "2021-10-05 12:55:17 EDT"
git2r::repository()
Local: main C:/Users/veruk/Desktop/Disco/Curso GitHub/intro_git-github
Remote: main @ origin (https://github.com/Julenasti/intro_git-github.git)
Head: [24194b8] 2021-09-28: correcciones ortograficas y organizacion del taller
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19042)
Matrix products: default
locale:
[1] LC_COLLATE=Spanish_Spain.1252 LC_CTYPE=Spanish_Spain.1252
[3] LC_MONETARY=Spanish_Spain.1252 LC_NUMERIC=C
[5] LC_TIME=Spanish_Spain.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods
[7] base
loaded via a namespace (and not attached):
[1] Rcpp_1.0.7 knitr_1.33 magrittr_2.0.1
[4] downlit_0.2.1 R6_2.5.0 rlang_0.4.11
[7] stringr_1.4.0 tools_4.0.3 xfun_0.23.1
[10] jquerylib_0.1.4 git2r_0.28.0 htmltools_0.5.1.1
[13] yaml_2.2.1 digest_0.6.27 assertthat_0.2.1
[16] crayon_1.4.1 purrr_0.3.4 sass_0.4.0
[19] distill_1.2 glue_1.4.2 evaluate_0.14
[22] rmarkdown_2.10 emo_0.0.0.9000 stringi_1.6.1
[25] compiler_4.0.3 bslib_0.2.5 generics_0.1.0
[28] jsonlite_1.7.2 lubridate_1.7.10